/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Problemas;

import Busquedas.*;
import GUI.Micromundo;
import GUI.Ventanas;
import GUI.Vista;
import java.util.Random;



public class Principal extends Problema {

        private int  planeta;
        private int i;
        private int j;
        private Arista arista;
        private Vista vista;
        private Micromundo mundo;
        private Ventanas bus,text;
        private int costeA;
        boolean trama;
        private String soluciones;
        private int planetaIni;


public Principal(){}
public Principal(Ventanas t,Micromundo m,Vista v, boolean tram,int pX,int pY,Arista a){
        vista=v;
        text=t;
        arista=a;
        trama=tram;
        i=pX;
        j=pY;
        
        int []paramObjetivo = {0,0};
        int []paramObjetivo1 = {0,18};
        int []paramObjetivo2 = {12,0};
        int []paramObjetivo3 = {12,18};
         int[] paramInicial={i,j};
        Estado inicial = new Estado(paramInicial);
	    Estado [] objetivo = new Estado[4];
	    objetivo[0] = new Estado(paramObjetivo);
        objetivo[1] = new Estado(paramObjetivo1);
        objetivo[2] = new Estado(paramObjetivo2);
        objetivo[3] = new Estado(paramObjetivo3);
	    String [] nombresOperadores={"padre","derecha","izquierda","arriba","abajo"};
        costeA=0;
        int [] costeOperadores={20,20,20,20};
        soluciones="";
        planeta=planetaCoor(i,j);
        planetaIni=planeta;
	    inicializa(inicial,objetivo,4,nombresOperadores,costeOperadores);
        mundo=m;
        mundo.redibuja(planeta);


}


public void asignaParametros(Estado actual){
		
        i=actual.getParametro(0);
        j=actual.getParametro(1);
        if (trama){
            text.escribeTexto("Planeta Origen:       "+Integer.toString(planetaCoor(i,j)));
            text.escribeTexto("Coordenadas         "+Integer.toString(i)+ "-"+Integer.toString(j));
        }else{
            soluciones=getSoluciones()+"Planeta Origen:       "+Integer.toString(planetaCoor(i,j))+'\n';
            soluciones=getSoluciones()+"Coordenadas      "+Integer.toString(i)+ " "+Integer.toString(j)+'\n';
        }
       


}

public int planetaCoor(int k,int x){
       int y=(i*19+j);
    return (k*19+x+1);
}


	public int getOperadorInverso(int op) {
		int inverso = -1;
		switch(op){
		case 0:
			inverso = 1;
			break;
		case 1:
			inverso = 0;
			break;
		case 2:
			inverso =3 ;
            break;
		case 3:
			inverso = 2;
			break;
        }
		return inverso;
	}
public int funcionHeuristica(Estado estado){

   int a=estado.getParametro(0);
   int b=estado.getParametro(1);

   if ((a==0&&b==0)||(a==0&&b==18)||(a==12&&b==0)||(a==12&&b==18))
       return 0;
   //la distancia minima al objetivo, suponiendo q todos los planetas 
   //intermedios esten a distancia minima(100);
   int valor1= (int)Math.abs(a+b)*100;
   int valor2= ((int)Math.abs(a)+(int)Math.abs(b-18))*100;
   int valor3= ((int)Math.abs(a-12)+(int)Math.abs(b))*100;
   int valor4= ((int)Math.abs(a-12)+(int)Math.abs(b-18))*100;
   return (int)Math.min(valor1,(int)Math.min(valor2,(int)Math.min(valor3,valor4)));
}




  	public Estado aplicaOperador(Estado actual,int dire){

        asignaParametros(actual);
        if (trama) mundo.redibuja(planetaCoor(i,j));
        Problema problemaLocal=null;
       // Busqueda busquedaLocal;
         Estado siguiente = null;
         
        if(direcCorrecta(dire)){
            siguiente = siguienteEstado(dire);
            int destino=dir(dire,i,j);
            this.setCosteOperador(dire,arista.dameCoste(planetaCoor(i,j),destino));
            int aux=planetaCoor(i,j);
            problemaLocal = arista.dameProblema(aux, destino);
            String nombreVentana=(problemaLocal.getClass().toString());
            nombreVentana=nombreVentana.substring(16,nombreVentana.length());
            if (trama==true){
                text.escribeTexto("Dirección: " + traduceDirecc(dire));
                text.escribeTexto("Planeta Destino: "+Integer.toString(destino));
                text.escribeTexto("Prueba a resolver: "+nombreVentana);
                text.escribeTexto("Distancia: "+Integer.toString(arista.dameCoste(planetaCoor(i,j),destino)));
                
            }else{

                soluciones=getSoluciones()+"Dirección: " + traduceDirecc(dire)+'\n';
                soluciones=getSoluciones()+("Planeta Destino: "+Integer.toString(destino))+'\n';
                soluciones=getSoluciones()+("Prueba a resolver: "+nombreVentana)+'\n';
                soluciones=getSoluciones()+("Distancia: "+Integer.toString(arista.dameCoste(planetaCoor(i,j),destino)))+'\n';
               
                
            }
        }
        else if (!direcCorrecta(dire)){
	     if (trama==true){
                text.escribeTexto("Dirección: " + traduceDirecc(dire));
                text.escribeTexto("DIRECCION AGUJERO NEGRO!!!!!!!!!!!!!!");
                text.escribeTexto("-------------------------------------------------------------");
                System.out.println("Dirección hacia agujero negro");
            }else{
                soluciones=getSoluciones()+("Dirección: " + traduceDirecc(dire))+'\n';
                soluciones=getSoluciones()+("DIRECCION AGUJERO NEGRO!!!!!!!!!!!!!!")+'\n';
                soluciones=getSoluciones()+("-------------------------------------------------------------")+'\n';

            }
 
    return null;
		}
        
      return siguiente;
	}
        
        
    public boolean resuelveProblema(int destino,int padre ,int dire,int valor ){
    
    boolean respuesta;
    Problema  problemaLocal = arista.dameProblema(padre, destino);
    Busqueda busquedaLocal;
     int tipoBusqueda;
        if (trama==true)
            tipoBusqueda= vista.lanzaVentanaBusquedas();
        else  {
             Random r=new Random();
             do{
                 tipoBusqueda=1+r.nextInt(10);
                 //tipoBusqueda=7;
             }while(tipoBusqueda==5||tipoBusqueda==10||tipoBusqueda==9);
            }
		switch(tipoBusqueda){
		case 1:
			busquedaLocal = new PrimeroAnchura(problemaLocal);
			break;
		case 2:
			busquedaLocal = new PrimeroProfundidad(problemaLocal);
			break;
		case 3:
			busquedaLocal = new CosteUniforme(problemaLocal);
			break;
		case 4:
			busquedaLocal = new ProfundizacionIterativa(problemaLocal);
			break;
		case 5: //hacer ventana para pedir profundidad simulado
            busquedaLocal = new ProfundidadLimitada(problemaLocal,vista.preguntaProfundidad());
                    break;
		case 6:
			busquedaLocal = new Voraz(problemaLocal);
			break;
		case 7:
			busquedaLocal = new AEstrella(problemaLocal);
			break;
		case 8: busquedaLocal = new EscaladaSimple(problemaLocal);
                     break;
		case 9: busquedaLocal = new MaximaPendiente(problemaLocal);
                    break;
		case 10: busquedaLocal = new EnfriamientoSimulado(problemaLocal, vista.pideTemperatura(),vista.pideEnfriamiento());
                       break;
		default:
		System.exit(-1);
		return false;
		}
        String nombreVentana=(problemaLocal.getClass().toString());
        nombreVentana=nombreVentana.substring(16,nombreVentana.length());
        String nombreVentana2=(busquedaLocal.getClass().toString());
        nombreVentana2=nombreVentana2.substring(16,nombreVentana2.length());
	if (busquedaLocal.buscar(vista.isControlCiclos()) != null){//TODO cambiar para que se pueda hacer o no control de ciclos
            respuesta=true;
            if (trama==true){
                text.escribeTexto("Viaje Seleccionado:");
                text.escribeTexto("  -Dirección: " + traduceDirecc(dire));
                text.escribeTexto("  -Planeta origen: "+Integer.toString(padre));
                text.escribeTexto("  -Planeta Destino: "+Integer.toString(destino));
                text.escribeTexto("  -Prueba a resolver: "+nombreVentana);
                text.escribeTexto("  -Búsqueda Seleccionada: "+nombreVentana2);
                text.escribeTexto("  -Heurística + coste:: "+Integer.toString(valor));
                text.escribeTexto(busquedaLocal.getCamino().toString());
                text.escribeTexto(busquedaLocal.getNombreOper().toString());
                text.escribeTexto("Nodos Expandidos: " + busquedaLocal.getExpandidos().size());
                text.escribeTexto( "Coste Prueba: " + busquedaLocal.getCosteCamino());
                //text.escribeTexto( "Distancia acumulado: " + Integer.toString(costeA+this.getCosteOperador(dire)));
                text.escribeTexto("Tiempo(ms): "+ busquedaLocal.getTiempoTotal()+"\n");
                text.escribeTexto("-------------------------------------------------------------");
            }else{
                 soluciones=getSoluciones()+("Viaje Seleccionado:"+'\n');
                 soluciones=getSoluciones()+("  -Dirección: " + traduceDirecc(dire))+'\n';
                 soluciones=getSoluciones()+("  -Planeta origen: "+Integer.toString(padre)+'\n');
                 soluciones=getSoluciones()+("  -Planeta Destino: "+Integer.toString(destino))+'\n';
                 soluciones=getSoluciones()+("  -Prueba a resolver: "+nombreVentana)+'\n';
                 soluciones=getSoluciones()+("  -Búsqueda Seleccionada: "+nombreVentana2)+'\n';
                 soluciones=getSoluciones()+("  -Heurística + coste:: "+Integer.toString(valor))+'\n';
                 soluciones=getSoluciones()+(busquedaLocal.getCamino().toString())+'\n';
                 soluciones=getSoluciones()+(busquedaLocal.getNombreOper().toString())+'\n';
                 soluciones=getSoluciones()+("Nodos Expandidos: " + busquedaLocal.getExpandidos().size())+'\n';
                 soluciones=getSoluciones()+( "Coste Prueba: " + busquedaLocal.getCosteCamino())+'\n';
                // soluciones=getSoluciones()+( "Distancia acumulado: " + Integer.toString(costeA+this.getCosteOperador(dire)))+'\n';
                 soluciones=getSoluciones()+("Tiempo(ms): "+ busquedaLocal.getTiempoTotal()+'\n');
                 soluciones=getSoluciones()+("-------------------------------------------------------------"+'\n');
            }
            

		}else{
            respuesta=false;
            if (trama==true){
                text.escribeTexto("Viaje Seleccionado:");
                text.escribeTexto("  -Dirección: " + traduceDirecc(dire));
                text.escribeTexto("  -Planeta origen: "+Integer.toString(padre));
                text.escribeTexto("  -Planeta Destino: "+Integer.toString(destino));
                text.escribeTexto("  -Prueba a resolver: "+nombreVentana);
                text.escribeTexto("  -Búsqueda Seleccionada: "+nombreVentana2);
                text.escribeTexto("  -Distancia total + Heuristica: "+Integer.toString(valor));
                text.escribeTexto("NO ENCUENTRO SOLUCION A ESTE PROBLEMA, busco siguiennte planeta con mejor estimacion" + "\n");
                text.escribeTexto("-------------------------------------------------------------"+'\n');
            }else{
                soluciones=getSoluciones()+("Viaje Seleccionado:"+'\n');
                 soluciones=getSoluciones()+("  -Dirección: " + traduceDirecc(dire))+'\n';
                 soluciones=getSoluciones()+("  -Planeta origen: "+Integer.toString(padre)+'\n');
                 soluciones=getSoluciones()+("  -Planeta Destino: "+Integer.toString(destino))+'\n';
                 soluciones=getSoluciones()+("  -Prueba a resolver: "+nombreVentana)+'\n';
                 soluciones=getSoluciones()+("  -Búsqueda Seleccionada: "+nombreVentana2)+'\n';
                 soluciones=getSoluciones()+("  -Distancia total + Heuristica: "+Integer.toString(valor))+'\n';
                soluciones=getSoluciones()+("NO ENCUENTRO SOLUCION A ESTE PROBLEMA, busco siguiennte planeta con mejor estimacion" + "\n")+'\n';
                soluciones=getSoluciones()+"-------------------------------------------------------------"+'\n';
            }

            }    
        return respuesta;
    
    }    

   	private String traduceDirecc(int dire){
		String s = "";
		switch(dire){
	    case 0:
			s="DERECHA";
			break;
		case 1:
			s="IZQUIERDA";
			break;
		case 2:
			s="ARRIBA";
			break;
        case 3:
			s="ABAJO";
			break;
		}
		return s;
	}
private boolean direcCorrecta(int dire){
	//Si estando en un planeta compruebo si al aplicar el operador se cumple
    switch(dire){
	    case 0:
			//derecha
            if (j==18)
				return false;
			break;
		case 1:
			//s="IZQUIERDA";
			if (j==0)
				return false;
			break;
		case 2:
		//	s="ARRIBA";
			if (i==0)
				return false;
			break;
        case 3:
			//s="ABAJO";
			if (i==12)
				return false;
			break;
		default:
			return false;
		}
		return true;
	}
private Estado siguienteEstado(int dire){
	//Si estando en un planeta compruebo si al aplicar el operador se cumple
    int x,k;
    x=i;
    k=j;
    switch(dire){
	    case 0:
			//derecha
                k++;
                break;
		case 1:
			//s="IZQUIERDA";
                k--;

                break;
		case 2:
		//	s="ARRIBA";
                x--;

                break;
        case 3:
			//s="ABAJO";
                x++;

                break;

        }
        int [] param={x,k};
		return new Estado(param);
	}
private int dir(int dire,int i,int j){
	//Si estando en un planeta compruebo si al aplicar el operador se cumple
    //int k,x;
    int k=j;
    int x=i;
    switch(dire){
	    case 0:
			//derecha
                k++;
                break;
		case 1:
			//s="IZQUIERDA";
                k--;

                break;
		case 2:
		//	s="ARRIBA";
                x--;

                break;
        case 3:
			//s="ABAkO";
                x++;

                break;

        }

		return planetaCoor(x,k);
	}

    /**
     * @return the soluciones
     */
    public String getSoluciones() {
        return soluciones;
    }

    public int inicial() {
        return planetaIni;
    }

    public void escribe(int c,int a,int b){
         if (trama){
             text.escribeTexto( "Valor heurístico: " + Integer.toString(b));
             text.escribeTexto( "Distancia acumulada (Hasta planeta origen): " + Integer.toString(c));
             text.escribeTexto( "Distancia total + Heuristica: " + Integer.toString(a));
             text.escribeTexto("-------------------------------------------------------------"+'\n');
         }
         else  {
             soluciones=getSoluciones()+( "Valor heurístico: " + Integer.toString(b))+'\n';
             soluciones=getSoluciones()+( "Distancia acumulada (Hasta planeta origen): " + Integer.toString(c))+'\n';
             soluciones=getSoluciones()+( "Distancia total + Heuristica: " + Integer.toString(a))+'\n';
              soluciones=getSoluciones()+("-------------------------------------------------------------")+'\n';
         }
    }



}